package com.eltonkent.dashboard.ui;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.graphics.drawable.AnimationDrawable;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.Vibrator;
import android.text.Html;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ViewFlipper;

import com.eltonkent.dashboard.R;
import com.eltonkent.dashboard.constants.ApplicationConstants;
import com.eltonkent.dashboard.data.container.WeatherContainer;
import com.eltonkent.dashboard.service.ServiceManagerImpl;
import com.eltonkent.dashboard.util.gps.DashboardLocationManager;
import com.eltonkent.dashboard.util.gps.GPSUtil;
import com.eltonkent.dashboard.util.gps.ILocationListener;
import com.eltonkent.dashboard.util.logger.Logger;
import com.eltonkent.dashboard.util.sensor.DashboardSensorManager;

public class DashboardActivity extends Activity implements ILocationListener {

	private static class CurrentUnitPreference {
		private static int trip;
		private static int altitude;
		private static int speed;
		private static int acceleration;
		private static int coordinate;
		private static int temp;

		private static int overspeedInKM = 90;
		private static int overspeedInM = 55;
		private static int overspeedInNM = 50;
	}

	private final String TAG = "DBA";

	private DashboardSensorManager sensorManager;
	private static final String TRIP_PREF = "lasttripvalue";
	private TextView speed;
	private TextView speedScale;
	private TextView trip;
	private TextView tripScale;
	private TextView accel;
	private TextView accelScale;
	private TextView humidity;
	private TextView temp;
	private TextView tempScale;
	private TextView baro;
	private TextView baroScale;
	private TextView alti;
	private TextView altiScale;
	private TextView meter;
	private TextView meterScale;
	private TextView anemo;
	private TextView anemoScale;

	private TextView location;
	private ImageView movementLED;
	private ViewFlipper overSpeedFlipper;
	private TextView sunRise;
	private TextView sunSet;

	private Button btnPrevAddress;
	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case UPDATE_SPEED_TRIP:
				Location currLoc = (Location) msg.obj;
				if (oldLocation != null) {
					updateGauges(currLoc);
				}
				break;
			case GEOCODING:
				if (msg.arg1 < 0) {
					if (previousAddress != null) {
						btnPrevAddress.setVisibility(View.VISIBLE);
					} else {
						location.setText(R.string.addresserror);
					}
				} else {
					location.setText((String) msg.obj);
					btnPrevAddress.setVisibility(View.GONE);
				}
				break;
			case DIALOG_GPS_PROG:
				showDialog(DIALOG_GPS_PROG);
				break;
			case SHOW_MOVEMENT_LED:
				movementLED.setImageResource(R.drawable.green_led);
				break;
			case SET_ALTITUDE:
				alti.setText((String) msg.obj);
				break;
			case WEATHER:
				processWeatherInfo();
			}
		}
	};

	private WeatherContainer currentWeather;

	private boolean canUpdateTripmeter = true;

	private boolean causedByLongClick;

	private PowerManager.WakeLock wakeLock = null;

	private static final int OPEN_GPS_SETTINGS = 30;

	private static final int OPEN_PREFERENCES = 50;

	private DashboardLocationManager locationManager;

	private static final int DIALOG_GPS_PROG = 10;
	private static final int DIALOG_GPS_TIMEOUT = 12;

	private static final int SHOW_MOVEMENT_LED = 20;

	private static final int SET_ALTITUDE = 40;

	private static final int UPDATE_SPEED_TRIP = 60;

	private static final int GEOCODING = 80;

	private static final int WEATHER = 100;

	private boolean isGPSDialogShown;

	private String previousAddress;

	private Location oldLocation;

	private long oldLocationFixTime;

	private double currentSubTrip;

	private double currentMainTrip;

	private void checkLocationManager() {
		if (!locationManager.hasProvider()) {
			showNoProviderDialog();
		} else {
			if (!locationManager.isRunning()) {
				startLocationSearch();
			}
		}
	}

	private void dimissGPSLoadDialog() {
		if (isGPSDialogShown) {
			
			dismissDialog(DIALOG_GPS_PROG);
			isGPSDialogShown = false;
		}
	}

	private SharedPreferences getApplicationPreferences() {
		return getSharedPreferences(ApplicationConstants.PREFERENCE_FILE,
				MODE_PRIVATE);
	}

	/**
	 * To preserve accuracy, this method should return immediately
	 */
	@Override
	public void locationProviderDisabled() {
		showNoProviderDialog();
	}

	// private void inflateMenu(Menu menu, int id) {
	// MenuInflater inflater = getMenuInflater();
	// inflater.inflate(id, menu);
	// }

	/**
	 * To preserve accuracy, this method should return immediately
	 */
	@Override
	public void locationSearchTimeout() {
		// dismissDialog( );
		removeDialog(DIALOG_GPS_PROG);
		showDialog(DIALOG_GPS_TIMEOUT);
		// new AlertDialog.Builder(this)
		// .setTitle(getString(R.string.gps))
		// .setMessage(R.string.gps_timeout)
		// .setPositiveButton(R.string.gps_retry,
		// new DialogInterface.OnClickListener() {
		// public void onClick(DialogInterface dialog,
		// int which) {
		// startLocationSearch();
		// }
		// })
		// .setNegativeButton(R.string.quit_app,
		// new DialogInterface.OnClickListener() {
		// @Override
		// public void onClick(DialogInterface dialog,
		// int which) {
		// dialog.dismiss();
		// shutdownApplication();
		// }
		// }).setCancelable(false).show();
	}

	@Override
	public void movementInitiated() {
		dimissGPSLoadDialog();
		handler.sendEmptyMessage(SHOW_MOVEMENT_LED);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {
		Logger.i(TAG, "onActivity Result");
		switch (requestCode) {
		case OPEN_GPS_SETTINGS:
			checkLocationManager();
			break;
		}
	}

	private ImageView weatherIcon;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.dashboard);
		movementLED = (ImageView) findViewById(R.id.movingled);
		Typeface tf = Typeface.createFromAsset(getAssets(), "font/DIGI.TTF");
		speed = (TextView) findViewById(R.id.speedText);
		speedScale = (TextView) findViewById(R.id.speedScale);
		trip = (TextView) findViewById(R.id.tripText);
		tripScale = (TextView) findViewById(R.id.tripScale);
		accel = (TextView) findViewById(R.id.accelText);
		accelScale = (TextView) findViewById(R.id.accelScale);
		humidity = (TextView) findViewById(R.id.humidityText);
		temp = (TextView) findViewById(R.id.tempText);
		tempScale = (TextView) findViewById(R.id.tempScale);

		baro = (TextView) findViewById(R.id.baroText);
		baroScale = (TextView) findViewById(R.id.baroScale);
		alti = (TextView) findViewById(R.id.altiText);
		altiScale = (TextView) findViewById(R.id.altiScale);
		anemo = (TextView) findViewById(R.id.anemoText);
		anemoScale = (TextView) findViewById(R.id.anemoScale);
		meter = (TextView) findViewById(R.id.meterText);
		meterScale = (TextView) findViewById(R.id.meterScale);
		location = (TextView) findViewById(R.id.location);
		weatherIcon = (ImageView) findViewById(R.id.weathericon);

		/* Set the typefaces */
		speed.setTypeface(tf, Typeface.BOLD);
		speedScale.setTypeface(tf);
		trip.setTypeface(tf, Typeface.BOLD);
		tripScale.setTypeface(tf);
		alti.setTypeface(tf, Typeface.BOLD);
		altiScale.setTypeface(tf);
		accel.setTypeface(tf, Typeface.BOLD);
		accelScale.setTypeface(tf);
		humidity.setTypeface(tf, Typeface.BOLD);
		temp.setTypeface(tf, Typeface.BOLD);
		tempScale.setTypeface(tf);
		anemo.setTypeface(tf, Typeface.BOLD);
		anemoScale.setTypeface(tf);
		baro.setTypeface(tf, Typeface.BOLD);
		baroScale.setTypeface(tf);
		alti.setTypeface(tf, Typeface.BOLD);
		altiScale.setTypeface(tf);

		location.setTypeface(tf, Typeface.BOLD);
		((TextView) findViewById(R.id.overspeedtext)).setTypeface(tf);
		((TextView) findViewById(R.id.moveText)).setTypeface(tf);
		/* Sunrise/sunset info */
		((TextView) findViewById(R.id.sunriseText)).setTypeface(tf);
		((TextView) findViewById(R.id.humidityScale)).setTypeface(tf);
		sunRise = (TextView) findViewById(R.id.sunriseScale);
		sunRise.setTypeface(tf, Typeface.BOLD);
		((TextView) findViewById(R.id.sunsetText)).setTypeface(tf);
		sunSet = (TextView) findViewById(R.id.sunsetScale);
		sunSet.setTypeface(tf, Typeface.BOLD);
		overSpeedFlipper = (ViewFlipper) findViewById(R.id.overspeed);
		meter.setTypeface(tf, Typeface.BOLD);
		meterScale.setTypeface(tf);

		/* Marquee location */
		location.setSelected(true);
		Button image = (Button) findViewById(R.id.reset);
		image.setOnLongClickListener(new View.OnLongClickListener() {

			@Override
			public boolean onLongClick(View v) {
				Log.d("DBA", "tripmeter long click");
				resetTripmeter();
				causedByLongClick = true;
				return true;
			}
		});
		image.setOnClickListener(clickListener);
		btnPrevAddress = (Button) findViewById(R.id.prevLocation);
		btnPrevAddress.setOnClickListener(clickListener);

		final Button btnSettings = (Button) findViewById(R.id.settings);
		btnSettings.setOnClickListener(clickListener);
		startupApplication();
		// checkLocationManager();
	}

	private View.OnClickListener clickListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.settings:
				Intent preferenceIntent = new Intent().setClass(
						getApplicationContext(),
						com.eltonkent.dashboard.ui.DashboardPreferences.class);
				startActivityForResult(preferenceIntent, OPEN_PREFERENCES);
				break;
			case R.id.reset:
				if (causedByLongClick) {
					causedByLongClick = false;
				} else {
					toogleTripmeter();
				}
				break;
			case R.id.prevLocation:
				if (previousAddress != null) {
					location.setText(previousAddress);
				}
				btnPrevAddress.setVisibility(View.GONE);
				break;
			case R.id.cancelExit:
				removeDialog(DIALOG_GPS_TIMEOUT);
				shutdownApplication();
				break;
			case R.id.retry:
				removeDialog(DIALOG_GPS_TIMEOUT);
				startLocationSearch();
				break;
			}
		}
	};

	protected void onPrepareDialog(int id, Dialog dialog) {

	}

	private class GPSAni implements Runnable {
		public void run() {
			gpsAnimation.start();
		}
	}

	private AnimationDrawable gpsAnimation;

	@Override
	protected Dialog onCreateDialog(int dialogId) {
		Dialog dialog = null;
		switch (dialogId) {
		case DIALOG_GPS_PROG:
			dialog = new Dialog(this);
			dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
			View view = dialog.getLayoutInflater().inflate(
					R.layout.dialog_gps_loading, null);
			Button cancelExit = (Button) view.findViewById(R.id.cancelExit);
			cancelExit.setOnClickListener(clickListener);
			gpsAnimation = new AnimationDrawable();
			gpsAnimation.addFrame(
					getResources().getDrawable(R.drawable.gpsone), 200);
			gpsAnimation.addFrame(
					getResources().getDrawable(R.drawable.gpstwo), 200);
			gpsAnimation.addFrame(
					getResources().getDrawable(R.drawable.gpsthree), 200);
			gpsAnimation.addFrame(getResources()
					.getDrawable(R.drawable.gpsfour), 200);
			gpsAnimation.setOneShot(false);

			ImageView ani = (ImageView) view.findViewById(R.id.animation);
			ani.setBackgroundDrawable(gpsAnimation);
			// AnimationDrawable d = (AnimationDrawable) ani.getBackground();
			// d.start();
			ani.post(new GPSAni());
			dialog.setContentView(view);// R.layout.dialog_gps_loading);

			dialog.setCancelable(false);
			return dialog;
		case DIALOG_GPS_TIMEOUT:
			dialog = new Dialog(this);
			dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
			View timeOutview = dialog.getLayoutInflater().inflate(
					R.layout.dialog_gps_timeout, null);
			Button retry=(Button) timeOutview.findViewById(R.id.retry);
			Button quit=(Button) timeOutview.findViewById(R.id.cancelExit);
			quit.setOnClickListener(clickListener);
			retry.setOnClickListener(clickListener);
			dialog.setContentView(timeOutview);
			dialog.setCancelable(false);
			
//			dialog = new AlertDialog.Builder(this)
//					.setTitle(getString(R.string.gps))
//					.setMessage(R.string.gps_timeout)
//					.setPositiveButton(R.string.gps_retry,
//							new DialogInterface.OnClickListener() {
//								public void onClick(DialogInterface dialog,
//										int which) {
//									
//								}
//							})
//					.setNegativeButton(R.string.quit_app,
//							new DialogInterface.OnClickListener() {
//								@Override
//								public void onClick(DialogInterface dialog,
//										int which) {
//									dialog.dismiss();
//									shutdownApplication();
//								}
//							}).setCancelable(false).create();
			return dialog;
		}
		return null;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (wakeLock != null) {
			Logger.i(TAG, "Releasing wake lock");
			wakeLock.release();
		}
	}

	// @Override
	// public boolean onCreateOptionsMenu(Menu menu) {
	// inflateMenu(menu, R.menu.dashboardmenu);
	// return true;
	// }

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			shutdownApplication();
			return true;
		}
		return false;
	}

	@Override
	protected void onResume() {
		super.onResume();
		Logger.d(TAG, "Dashboard Activity onResume!");
		setUiBasedOnPreferences();
		if (!locationManager.isRunning()) {
			checkLocationManager();
		}
	}

	private void processWeatherInfo() {
		humidity.setText(currentWeather.getHumidity());
		switch (CurrentUnitPreference.temp) {
		case 0:
			temp.setText(currentWeather.getTempInCelcius());
			break;
		case 1:
			temp.setText(currentWeather.getTempInFaren());
			break;
		case 2:
			temp.setText(currentWeather.getTempInKelvin());
			break;
		}
		anemo.setText(currentWeather.getWindCondition());
		anemoScale.setText(currentWeather.getWindScale());
		if (currentWeather.getWeatherCondition() > 0) {
			switch (currentWeather.getWeatherCondition()) {
			case 1:
				weatherIcon.setImageResource(R.drawable.sun);
				break;
			case 2:
				weatherIcon.setImageResource(R.drawable.snow);
				break;
			case 3:
				weatherIcon.setImageResource(R.drawable.cloud);
				break;
			case 4:
				weatherIcon.setImageResource(R.drawable.rain);
				break;
			case 5:
				weatherIcon.setImageResource(R.drawable.fog);
				break;
			case 6:
				weatherIcon.setImageResource(R.drawable.partlycloudy);
				break;
			}
		}

		if (!currentWeather.isGoogleResponse()) {
			baro.setText(currentWeather.getPressure());
			baroScale.setText(currentWeather.getPressureScale());

			sunRise.setText(currentWeather.getSunrise());
			sunSet.setText(currentWeather.getSunset());
		}
	}

	private void resetTripmeter() {
		Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		vibrator.vibrate(4000);
		trip.setText("0");
		meter.setText("0");
		currentMainTrip = 0;
		currentSubTrip = 0;
		vibrator.vibrate(1000);
	}

	/**
	 * To preserve accuracy, this method should return immediately
	 */
	@Override
	public void setAltitude(double altitude) {
		Message msg = new Message();
		// TODO convert to current unit
		msg.obj = String.valueOf(altitude);
		msg.what = SET_ALTITUDE;
		handler.sendMessage(msg);
		// TODO set the altimeter

	}

	private void setDashboardScale(SharedPreferences prefs) {
		String unit = prefs.getString(
				getResources().getString(R.string.key_unit_speed), "0");
		/* Speedometer scale */
		CurrentUnitPreference.speed = Integer.parseInt(unit);
		switch (CurrentUnitPreference.speed) {
		case 0:
			speedScale.setText(R.string.kmph);
			break;
		case 1:
			speedScale.setText(R.string.mph);
			break;
		case 2:
			speedScale.setText(R.string.nmph);
			break;
		}

		/* Tripmeter */
		unit = prefs.getString(
				getResources().getString(R.string.key_unit_trip), "0");
		CurrentUnitPreference.trip = Integer.parseInt(unit);
		switch (CurrentUnitPreference.trip) {
		case 0:
			tripScale.setText(R.string.KM);
			meterScale.setText(R.string.meterScale);
			break;
		case 1:
			tripScale.setText(R.string.m);
			meterScale.setText(R.string.feet);
			break;
		case 2:
			tripScale.setText(R.string.nautm);
			meterScale.setText(R.string.meterScale);
			break;
		}

		/* Acceleration */
		unit = prefs.getString(
				getResources().getString(R.string.key_unit_accl), "0");
		CurrentUnitPreference.acceleration = Integer.parseInt(unit);
		switch (CurrentUnitPreference.acceleration) {
		case 0:
			accelScale.setText(R.string.accelscale);
			break;
		case 1:
			accelScale.setText(R.string.gforce);
			break;
		}

		/* Temperature */
		unit = prefs.getString(
				getResources().getString(R.string.key_unit_temp), "0");
		CurrentUnitPreference.temp = Integer.parseInt(unit);
		switch (CurrentUnitPreference.temp) {
		case 0:
			tempScale.setText(R.string.centi);
			break;
		case 1:
			tempScale.setText(R.string.farhi);
			break;
		case 2:
			tempScale.setText(R.string.kelvin);
			break;
		}

		/* Altitude */
		unit = prefs.getString(getResources().getString(R.string.key_unit_alt),
				"0");
		CurrentUnitPreference.altitude = Integer.parseInt(unit);
		switch (CurrentUnitPreference.altitude) {
		case 0:
			altiScale.setText(R.string.feet);
			break;
		case 1:
			altiScale.setText(R.string.meters);
			break;
		}
	}

	/**
	 * Set the lcd background color based on
	 * 
	 * @param prefs
	 */
	private void setLCDColor(SharedPreferences prefs) {

		String color = prefs.getString(
				getResources().getString(R.string.key_lcd_color), "0");
		int bgDrawable = 0;
		switch (Integer.parseInt(color)) {
		case 0:
			bgDrawable = R.drawable.lcdgreen;
			break;
		case 1:
			bgDrawable = R.drawable.lcdblue;
			break;
		case 2:
			bgDrawable = R.drawable.lcdorange;
			break;
		}
		findViewById(R.id.one).setBackgroundResource(bgDrawable);
		findViewById(R.id.two).setBackgroundResource(bgDrawable);
		findViewById(R.id.three).setBackgroundResource(bgDrawable);
		findViewById(R.id.four).setBackgroundResource(bgDrawable);
		findViewById(R.id.five).setBackgroundResource(bgDrawable);
		findViewById(R.id.six).setBackgroundResource(bgDrawable);
		findViewById(R.id.seven).setBackgroundResource(bgDrawable);
		findViewById(R.id.eight).setBackgroundResource(bgDrawable);
		findViewById(R.id.nine).setBackgroundResource(bgDrawable);
	}

	@Override
	public void setLocation(Location location) {
		Message msg = new Message();
		msg.what = UPDATE_SPEED_TRIP;
		msg.obj = location;
		handler.sendMessage(msg);

	}

	@Override
	public void setLocationAddress(String address, boolean isAddressValid) {
		dimissGPSLoadDialog();
		Message message = new Message();
		message.what = GEOCODING;
		if (isAddressValid) {
			previousAddress = address;
			message.obj = address;
		} else {
			/* if its an invalid address show the previous button */
			message.arg1 = -1;
		}
		handler.sendMessage(message);
	}

	private void setScreenLock(boolean useLock) {
		if (useLock) {
			if (wakeLock != null) {
				PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
				wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
						"dashboard");
				wakeLock.acquire();
			}
		} else {
			if (wakeLock != null) {
				wakeLock.release();
			}
		}

	}

	private void setSpeed(int speed, boolean isOverspeed) {
		/* set the speedometer */
		this.speed.setText(String.valueOf(speed));
		if (isOverspeed) {
			overSpeedFlipper.startFlipping();
		} else {
			overSpeedFlipper.stopFlipping();
		}
	}

	private void setUiBasedOnPreferences() {
		SharedPreferences prefs = getApplicationPreferences();
		setDashboardScale(prefs);
		setLCDColor(prefs);
		boolean brightLock = prefs.getBoolean(
				getResources().getString(R.string.key_screen_on), true);
		if (brightLock) {
			setScreenLock(brightLock);
		}
		boolean useDataServices = prefs.getBoolean(
				getResources().getString(R.string.key_enable_data), true);
		locationManager.turnOffDataServices(useDataServices);

	}

	/*
	 * Location based callback
	 */

	@Override
	public void setWeatherInfo(WeatherContainer weatherInfo) {
		this.currentWeather = weatherInfo;
		Message msg = new Message();
		msg.what = WEATHER;
		handler.sendMessage(msg);
	}

	private void showGPSProgress() {
		handler.sendEmptyMessage(DIALOG_GPS_PROG);
	}

	private void showNoProviderDialog() {
		new AlertDialog.Builder(this)
				.setTitle(getString(R.string.gps_disabled_title))
				.setMessage(R.string.gps_disabled_message)
				.setPositiveButton(R.string.open_settings,
						new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog,
									int which) {
								Intent gpsOptionIntent = new Intent(
										android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
								startActivity(gpsOptionIntent);
								dialog.dismiss();
							}
						})
				.setNegativeButton(R.string.quit_app,
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								dialog.dismiss();
								shutdownApplication();
							}
						}).setCancelable(false).show();
	}

	private void shutdownApplication() {
		Logger.d("DBA", "Shutting down application");
		SharedPreferences prefs = getApplicationPreferences();
		SharedPreferences.Editor edit = prefs.edit();
		edit.putString(TRIP_PREF, trip.getText().toString());
		edit.commit();
		locationManager.shutdownLocationManager();
		ServiceManagerImpl.getInstance().cancelAllTasks();
		ServiceManagerImpl.getInstance().shutdown();
		Logger.shutdown();
		finish();
		System.exit(0);
	}

	private void startLocationSearch() {

		// TODO uncomment
		isGPSDialogShown = true;
		showGPSProgress();
		locationManager.startGetLocation();
	}

	private void startupApplication() {

		locationManager = new DashboardLocationManager(this, this);
		sensorManager = new DashboardSensorManager();
		setUiBasedOnPreferences();

	}

	private void toogleTripmeter() {
		canUpdateTripmeter = !canUpdateTripmeter;
	}

	private void updateGauges(Location newLocation) {
		// 3.6 km/h = 1 m/s, the SI unit of speed, metre per second
		// 1 km/h = 0.277 78 m/s
		// 1 km/h = 0.621 37 mph = 0.911 34 feet per second
		// 1 knot = 1.852 km/h (exactly)
		// 1 mile per hour = 1.609344 km/h (~1.61 km/h)[3]

		// time taken to travel from old to new location in seconds
		double timeTakenInSecs = (newLocation.getTime() - oldLocationFixTime) / 1000;
		double distanceinMetres = GPSUtil.getDistanceBetweenInKM(oldLocation,
				newLocation) * 1000;
		updateTripmeter(distanceinMetres);

		/* calulate speed in meters per second */
		double speedInMetersPerSec = distanceinMetres / timeTakenInSecs;
		double speedInKilometerPerHour = speedInMetersPerSec / 3.6;
		int calculatedSpeed = 0;
		boolean isOverspeed = false;
		switch (CurrentUnitPreference.speed) {
		// km/h
		case 0:
			calculatedSpeed = (int) speedInKilometerPerHour;
			isOverspeed = calculatedSpeed > CurrentUnitPreference.overspeedInKM;
			break;
		/* miles/h */
		case 1:
			calculatedSpeed = (int) (speedInKilometerPerHour / 1.609344);
			isOverspeed = calculatedSpeed > CurrentUnitPreference.overspeedInM;
			break;
		/* nautical miles/h */
		case 2:
			calculatedSpeed = (int) (speedInKilometerPerHour / 1.852);
			isOverspeed = calculatedSpeed > CurrentUnitPreference.overspeedInNM;
			break;
		}
		setSpeed(calculatedSpeed, isOverspeed);

		// in the end
		oldLocation = newLocation;
		oldLocationFixTime = oldLocation.getTime();
	}

	private void updateTripmeter(double meterstoAdd) {
		// 1 mile=5,280 feet
		// 1meter = 3.2808399 feet

		int multiple = 0;
		switch (CurrentUnitPreference.trip) {
		/* km */
		case 0:
			currentSubTrip += meterstoAdd;
			multiple = 1000;
			break;
		/* miles */
		case 1:
			currentSubTrip += (meterstoAdd * 3.2808399);
			multiple = 5280;
			/* naut miles */
		case 2:
			/* 1 nautical mile = 1852 meters */
			currentSubTrip += multiple = 1852;
			break;

		}
		if (currentSubTrip > multiple) {
			currentMainTrip++;
			currentSubTrip = currentSubTrip % multiple;
		}
		String mainTrip = String.valueOf((int) currentMainTrip);
		String subTrip = String.valueOf((int) currentSubTrip);
		this.trip.setText(mainTrip);
		this.meter.setText(subTrip);

	}

}
